package zbl.c0.symbol;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * 		符号表类
 * 	 根据文法可以知道，常、变量声明只能在程序最前面的全局声明、以及所有的函数定义的
 * 头部进行，所以依据该文法的特点将符号表的结构设置如下。
 * 
 * 		所有的添加过程，如果成功则返回true失败则返回false
 * 
 * @author 朱伯龙
 *
 */

public class SymbolTable {

	Hashtable<String, Symbol> globalTable;	//  存储全局常变量信息
	
	Hashtable<String, FuncTable> functable;	//  存储所有的函数信息，以及函数内部的符号表
	
	public SymbolTable(){
										//  分配存储空间
		globalTable = new Hashtable<String, Symbol>();
		functable = new Hashtable<String, FuncTable>();
		
	}
	
	/**
	 * 		根据全局符号名查找全局符号
	 * @param name
	 * @return
	 */
	public Symbol getGlobal(String name){
		Symbol sym = (Symbol) globalTable.get(name);
        return sym;
	}
	
	/**
	 * 		向全局符号表中添加符号
	 * @param name
	 * @param type
	 * @param value   根据类型来决定value到底是常量的值还是变量的地址
	 */
	public boolean addSym(String name, int type, int value){
		if(getGlobal(name)!=null){							//  该全局符号已经定义，  报错
			System.out.println("全局符号  "+name+"  已经定义");
			return false;
		}else{												//	向全局符号表中添加该符号
			Symbol sym;
			if(type == Symbol.CONST)						//  常量，则value表示常量的值，调用常量符号的构造方法
				sym = new Symbol(value, name);
			else											//  变量，则value表示变量的地址，调用变量符号的构造方法
				sym = new Symbol(name, value, 1);
			
			globalTable.put(sym.name, sym);
			return true;
		}
	}
	
	/**
	 * 		根据函数名名查找总函数表，返回该函数对应的函数表
	 * @param name
	 * @return
	 */
	public FuncTable getFunc(String name){
		FuncTable func = (FuncTable)functable.get(name);
		return func;
	}
	
	/**
	 * 		向总函数表中添加一个函数表
	 * @param curFunc
	 */
	public boolean addFunc(FuncTable curFunc){
		if(getFunc(curFunc.funcname) != null){
			System.out.println("函数  "+curFunc.funcname+"  已经定义，无法添加！！！");
			return false;
		}else{
			functable.put(curFunc.funcname, curFunc);
			return true;
		}
	}
	/**
	 * 		根据入口地址返回函数信息表
	 * 需要遍历函数表
	 * @param addr
	 * @return
	 */
	public FuncTable getfuncByaddr(int addr){
		FuncTable func = null;
		Enumeration<FuncTable> en = functable.elements();
	    while(en.hasMoreElements()){
	    	func = (FuncTable) en.nextElement();
	    	if(func.addr == addr)
	    		return func;
	    }
	    return null;
	}
	
	
}
